package com.clpms.service.impl;

import com.clpms.bean.enumBean.DataStatusEnum;
import com.clpms.bean.enumBean.ErrorCodeEnum;
import com.clpms.bean.req.AddCourseReq;
import com.clpms.bean.req.CourseQueryReq;
import com.clpms.bean.req.DeleteCourseReq;
import com.clpms.bean.req.UpdateCourseReq;
import com.clpms.bean.resp.CourseQueryResp;
import com.clpms.bean.resp.LearnRecordForWorkResp;
import com.clpms.dao.mapper.CourseDao;
import com.clpms.dao.mapper.LearnRecordDao;
import com.clpms.dao.mapper.WorkDao;
import com.clpms.dao.pojo.Course;
import com.clpms.dao.pojo.LearnRecord;
import com.clpms.service.CourseService;
import com.clpms.utils.CommonException;
import com.clpms.utils.CurrentUser;
import com.clpms.utils.UserUtils;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author caixinyong
 * @date 2023/5/9 8:01 PM
 */


@Service
@Slf4j
public class CourseServiceImpl implements CourseService {
    @Resource
    private CourseDao courseDao;
    @Resource
    private LearnRecordDao learnRecordDao;
    @Resource
    private WorkDao workDao;

    @Override
    public PageInfo<CourseQueryResp> query(CourseQueryReq req) {
        CurrentUser currentUser = UserUtils.get();
        PageHelper.startPage(req.getPageNum(), req.getPageSize());
        List<Course> courseList = courseDao.queryByKeyWord(
                req.getKeyWord(), req.getAssessmentMethod(), currentUser.getSchoolId(), currentUser.getTeacherId(),
                DataStatusEnum.NORMAL.getCode()
        );
        List<CourseQueryResp> respList =
                courseList.stream().map(this::convertToQueryCourseResp).collect(Collectors.toList());
        PageInfo<CourseQueryResp> pageInfo = new PageInfo<>(respList);
        return pageInfo;
    }

    @Override
    public Boolean delete(DeleteCourseReq req) {
        CurrentUser currentUser = UserUtils.get();
        Course course = courseDao.queryById(
                req.getCourseId(), currentUser.getSchoolId(), currentUser.getTeacherId(),
                DataStatusEnum.NORMAL.getCode()
        );
        if (Objects.isNull(course)) {
            throw new CommonException(ErrorCodeEnum.PARAM_ERROR.getCode(), "课程不存在");
        }
        Long result = courseDao.deleteById(
                req.getCourseId(), currentUser.getSchoolId(), currentUser.getTeacherId(),
                DataStatusEnum.NORMAL.getCode()
        );
        workDao.deleteByCourseId(req.getCourseId(), currentUser.getSchoolId(), currentUser.getTeacherId());
        learnRecordDao.deleteByCourseId(req.getCourseId(), currentUser.getSchoolId(), currentUser.getTeacherId());
        return Boolean.TRUE;
    }

    /**
     * 添加课程
     *
     * @param req
     * @return
     */
    @Override
    public Boolean addCourse(AddCourseReq req) {
        CurrentUser currentUser = UserUtils.get();
        String courseNo = req.getCourseNo();
        checkCourse(courseNo, req.getName(), currentUser, null);

        Course insert = Course.builder()
                .courseNo(req.getCourseNo())
                .name(req.getName())
                .assessmentMethod(req.getAssessmentMethod())
                .assessmentContent(Optional.ofNullable(req.getAssessmentContent()).orElse(StringUtils.EMPTY))
                .remark(Optional.ofNullable(req.getRemark()).orElse(StringUtils.EMPTY))
                .schoolId(currentUser.getSchoolId())
                .teacherId(currentUser.getTeacherId())
                .build();
        courseDao.insert(insert);
        return Boolean.TRUE;
    }

    @Override
    public Boolean updateCourse(UpdateCourseReq req) {
        CurrentUser currentUser = UserUtils.get();
        Course course = courseDao.queryById(
                req.getId(), currentUser.getSchoolId(), currentUser.getTeacherId(), DataStatusEnum.NORMAL.getCode()
        );
        if (Objects.isNull(course)) {
            throw new CommonException(ErrorCodeEnum.PARAM_ERROR.getCode(), "没有该课程");
        }
        checkCourse(req.getCourseNo(), req.getName(), currentUser, req.getId());

        Course update = Course.builder()
                .id(req.getId())
                .courseNo(req.getCourseNo())
                .name(req.getName())
                .assessmentMethod(req.getAssessmentMethod())
                .assessmentContent(req.getAssessmentContent())
                .remark(req.getRemark())
                .build();

        courseDao.updateById(update);

        return Boolean.TRUE;
    }

    @Override
    public List<CourseQueryResp> queryAllCourse() {
        CurrentUser currentUser = UserUtils.get();
        List<Course> allCourse =
                courseDao.selectAllCourse(currentUser.getSchoolId(), currentUser.getTeacherId(),
                        DataStatusEnum.NORMAL.getCode());
        List<CourseQueryResp> respList = allCourse.stream().map(course ->
                CourseQueryResp.builder().id(course.getId()).courseNameAndNo(String.format("%s [编号:%s]",
                        course.getName(), course.getCourseNo())).build()
        ).collect(Collectors.toList());
        return respList;
    }

    private Boolean checkCourse(String courseNo, String courseName, CurrentUser currentUser, Long id) {

        //校验编号
        Course course = courseDao.queryByCourse(
                courseNo, currentUser.getSchoolId(), currentUser.getTeacherId(), DataStatusEnum.NORMAL.getCode()
        );
        if (Objects.nonNull(course) && !Objects.equals(id, course.getId())) {
            throw new CommonException(ErrorCodeEnum.PARAM_ERROR.getCode(), String.format("【%s】是课程【%s】的编号，请修改编号",
                    course.getCourseNo(),
                    course.getName()));
        }

        //校验名称
        course = courseDao.queryByName(
                courseName, currentUser.getSchoolId(), currentUser.getTeacherId(), DataStatusEnum.NORMAL.getCode()
        );
        if (Objects.nonNull(course) && !Objects.equals(id, course.getId())) {
            throw new CommonException(ErrorCodeEnum.PARAM_ERROR.getCode(), String.format("【%s】是课程编号为【%s】的名称，请修改名称",
                    course.getName(),
                    course.getCourseNo()));
        }
        return Boolean.TRUE;
    }

    private CourseQueryResp convertToQueryCourseResp(Course course) {
        Long courseId = course.getId();
        List<LearnRecord> learnRecords = learnRecordDao.selectByCourseId(courseId);
        List<LearnRecordForWorkResp> recordForWorkResps =
                learnRecords.stream().map(learnRecord ->
                                LearnRecordForWorkResp.builder()
                                        .id(learnRecord.getId())
                                        .remark(learnRecord.getRemark())
                                        .score(learnRecord.getScore())
                                        .completionTime(learnRecord.getCompletionTime())
                                        .easyType(learnRecord.getEasyType())
                                        .progress(learnRecord.getProgress())
                                        .workId(learnRecord.getWorkId())
                                        .build())
                        .collect(Collectors.toList());

        Long totalWorkNumber = workDao.selectCountByCourseId(courseId);

        List<LearnRecordForWorkResp> learnRecordListByCourse;
        return CourseQueryResp
                .builder()
                .id(courseId)
                .courseNo(course.getCourseNo())
                .name(course.getName())
                .schoolId(course.getSchoolId())
                .teacherId(course.getTeacherId())
                .assessmentMethod(course.getAssessmentMethod())
                .assessmentContent(course.getAssessmentContent())
                .remark(course.getRemark())
                .createTime(course.getCreateTime())
                .updateTime(course.getUpdateTime())
                .learnRecordForWorkResp(recordForWorkResps)
                .totalLearnRecordNumber(recordForWorkResps.size())
                .totalWorkNumber(totalWorkNumber)
                .build();
    }
}
